package com.youth.routercore

import android.content.Intent
import com.example.lib_router_anntation.Module
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.*

object RouterCore {

    private val moduleController by lazy { ModuleController() }
    private val interceptorController by lazy { InterceptorController() }
    private val routerPathDispatcher by lazy { RouterPathDispatcher() }
    private val routerServiceDispatcher by lazy { RouterServiceDispatcher() }

    fun addModuleName(moduleName: String) {
        try {
            val cls = Class.forName(moduleName)
            if (Module::class.java.isAssignableFrom(cls)) {
                val module = cls.newInstance() as Module
                addModule(module)
            }
        } catch (ignore: Exception) {
            //ignore
        }
    }

    fun addModule(module: Module) = moduleController.addModule(module)

    fun removeModule(module: Module) = moduleController.removeModule(module)

    fun queryRouterPath(scheme: String): RouterPathRequest =
        moduleController.queryRouterPath(scheme)

    fun queryRouterService(identity: String): RouterServiceRequest =
        moduleController.queryRouterService(identity)

    fun addInterceptor(interceptor: RouterInterceptor) =
        interceptorController.addInterceptor(interceptor)

    fun removeInterceptor(interceptor: RouterInterceptor) =
        interceptorController.removeInterceptor(interceptor)

    @OptIn(FlowPreview::class)
    fun dispatchRouterPath(
        routerPathRequest: RouterPathRequest,
        needResult: Boolean
    ): Flow<Result<Intent>> {
        val needIntercept = routerPathRequest.needIntercept
        val interceptor = interceptorController.shouldIntercept(routerPathRequest)
        if (needIntercept && true == interceptor?.interceptJump(routerPathRequest)) {
            return flow {
                interceptor.intercept(routerPathRequest)
            }
        }
        return flow {
            if (needIntercept) {
                interceptor?.intercept(routerPathRequest)
            }
            emit(Unit)
        }.flatMapConcat {
            routerPathDispatcher.dispatch(routerPathRequest, needResult)
        }
    }

    fun dispatchRouterService(routerServiceRequest: RouterServiceRequest): Any? {
        return routerServiceDispatcher.dispatch(routerServiceRequest)
    }
}